#include "GRO_Group.h"
#include <list>


// Every child of Widget should use these in draw()
#define DRAW_BOX     painters.box.draw(area, _gui->getRenderer());
#define DRAW_FRAME   painters.frame.draw(area, _gui->getRenderer());
#define DRAW_DESIGN  painters.design.drawDesign(area, designPush, _gui->getRenderer());

namespace GRO
{
    Grid::Grid()
            : rows(0)
            , columns(0)
            , useSizeLimit(false)
    {}
    

    Widget* Grid::get(unsigned int row, unsigned int col)
    {
        if (row < contents.size() && col < contents[row].size())
        {
            return contents[row][col];
        }
        return NULL;
    }

    void Grid::set(unsigned int row, unsigned int col, Widget* value)
    {
        while (row >= contents.size())
        {
            contents.push_back(std::vector<Widget*>());
        }
        /*for(int r = 0; r < row + 1; r++)
        {
            while (col >= contents[r].size())
            {
                contents[r].push_back(NULL);
            }
        }*/
        while (col >= contents[row].size())  // I should probably loop through all? Yeah.
        {
            contents[row].push_back(NULL);
        }
        contents[row][col] = value;
        if (row >= rows)
            rows = row + 1;
        if (col >= columns)
            columns = col + 1;
        
        // FIXME: This was crashing, but I don't even think it is necessary.
        // Loop through all rows, filling out the columns.
        /*for (unsigned int r = 0; r < rows; r++)
        {
            int oldColumns = contents[r].size();
            while (columns > oldColumns)
            {
                contents[r].push_back(NULL);
                oldColumns++;
            }
        }*/
    }

    void Grid::add(Widget* value, bool newRow)
    {
        if(!newRow)
        {
            /*for (unsigned int r = 0; r < rows; ++r)
            {
                for (unsigned int c = 0; c < columns; ++c)
                {
                    if (contents[r][c] == NULL)
                    {
                        contents[r][c] = value;
                        return;
                    }
                }
            }*/
            set(currentAddPos.h, currentAddPos.w, value);
            if(!useSizeLimit || currentAddPos.w + 1 < columns)
                currentAddPos.w++;
            else
            {
                currentAddPos.w = 0;
                currentAddPos.h++;
            }
        }
        else
        {
            currentAddPos.h++;
            set(currentAddPos.h, 0, value);
            currentAddPos.w = 1;
        }
        // Didn't find a space...  Just add it to the end.
        //set(rows, 0, value);
    }

    void Grid::setSize(unsigned int Rows, unsigned int Columns)
    {
        useSizeLimit = true;
        
        while (Rows >= contents.size())
        {
            contents.push_back(std::vector<Widget*>());
        }
        for (unsigned int i = 0; i < Rows; i++)
        {
            while (Columns >= contents[i].size())
            {
                contents[i].push_back(NULL);
            }
        }
        rows = Rows;
        columns = Columns;

        /*for (Uint16 i = 0; i < rows; i++)
        {
            contents.push_back(vector<Widget*>());
            for (Uint16 j = 0; j < columns; j++)
            {
                contents[i].push_back(NULL);
            }
        }*/
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
// ***************************
// ********** Group **********
// ***************************





Group::Group()
        : Widget(GROUP, Dimensions(0, 0))
        //, graph(NULL)
        //, scrollX(NULL)
        //, scrollY(NULL)
        , alignment(ALIGN_LEFT_UP)
        , xPadding(10)
        , yPadding(10)
        //, autoFitContents(0)
        , extentX(0)
        , extentY(0)
        //, oldXScroll(0)
        //, oldYScroll(0)
{
    PainterMap* painterMap = getPainterMap();
    if(painterMap != NULL)
    {
        painters.box = painterMap->Default_LightBoxPainter;
        painters.frame = painterMap->Default_GroupPainter;
    }
}

Group::Group(const Dimensions& dims)
        : Widget(GROUP, dims)
        //, graph(NULL)
        //, scrollX(NULL)
        //, scrollY(NULL)
        , alignment(ALIGN_LEFT_UP)
        , xPadding(10)
        , yPadding(10)
        //, autoFitContents(0)
        , extentX(0)
        , extentY(0)
        //, oldXScroll(0)
        //, oldYScroll(0)
{
    PainterMap* painterMap = getPainterMap();
    if(painterMap != NULL)
    {
        painters.box = painterMap->Default_LightBoxPainter;
        painters.frame = painterMap->Default_GroupPainter;
    }
}

Group::~Group()
{
    for(std::vector< std::vector<Widget*> >::iterator e = grid.contents.begin(); e != grid.contents.end(); e++)
    {
        for(std::vector<Widget*>::iterator f = e->begin(); f != e->end(); f++)
            delete *f;
    }
    
    //delete graph;
    
    for(std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); e++)
        delete *e;

    //delete scrollX;
    //delete scrollY;
}

void Group::sortPinned()
{
    // FIXME sort pinned by depth

    //if (autoFitContents)
        //fitContents();
}

//void updateRelCoords();

// change dimensions of the group to fit the widgets
//void fitContents(bool usePinned = true);

//void wrapContents(bool continueOnWrappedLines = true, bool compressSpaces = false);

void Group::setGridSize(unsigned int rows, unsigned int columns)
{
    grid.setSize(rows, columns);
}

void Group::addToNewRow(Widget* widget)
{
    add(widget, true);
}

/*void Group::setAddOrder(AddOrderEnum order)
{
    grid.addOrder = order;
}
AddOrderEnum Group::getAddOrder()
{
    return grid.addOrder;
}*/

Widget* Group::action(PointerCursor* mouse, ActionEnum actionType)
{
    if (_folded || _hidden || mouse == NULL)
        return NULL;
    if (InRect(mouse->mx, mouse->my, pos, dims))
        return this;
    return NULL;
}
Widget* Group::action(NavCursor* nav, ActionEnum actionType)
{
    if (_folded || _hidden || nav == NULL)
        return NULL;
    // Set new place for the nav to the first widget in my grid. FIXME
    return this;
}








    
std::list<Widget*> Group::getChildren()
{
    std::list<Widget*> children = pins;
    for(std::vector< std::vector<Widget*> >::iterator e = grid.contents.begin(); e != grid.contents.end(); e++)
    {
        for(std::vector<Widget*>::iterator f = e->begin(); f != e->end(); f++)
        {
            if(*f != NULL)// && (*f)->autoDelete)
                children.push_back(*f);
        }
    }
    
    return children;
}

/*void Group::updateRelCoords()
{
    if (pinned && relPinCoords != NULL && _group != NULL)
    {
        relPinCoords->get(_group->area, area);
        if (relPinCoordsOffset != NULL)
        {
            area.x += relPinCoordsOffset->x;
            area.y += relPinCoordsOffset->y;
        }
    }
    Widget* w;
    for (widgetList::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL)
        {
            w->updateRelCoords();
        }
    }
}*/


/*void Group::wrapContents(bool continueOnWrappedLines, bool compressSpaces)
{
    // move the widgets around to fit the group's dimensions
    // compressSpaces fills up each row, otherwise, the secondary dimension
    // of the group will be ignored.
    // continueOnWrappedLines means that if a widget is moved to the
    // next line because it was beyond the primary dimension, the next
    // widgets will be on the same line.
}*/

void Group::set(unsigned int row, unsigned int col, Widget* widget)
{
    if (widget != NULL)
    {
        widget->setGui(_gui);
        widget->setPanel(_panel);
        widget->setGroup(this);

        //if (_gui != NULL && _gui->autoApplyTheme && _gui->theme != NULL)
            //widget->applyTheme(_gui->theme, true);
    }

    grid.set(row, col, widget);

    updatePositions();
    //if (autoFitContents)
        //fitContents();
            
    //if(_gui != NULL)
        //_gui->registerWidget(widget);
}

void Group::add(Widget* widget, bool newRow)
{
    if (widget == NULL)
        return;

    widget->setGui(_gui);
    widget->setPanel(_panel);
    widget->setGroup(this);
    setChild(widget);

    //if (_gui != NULL && _gui->autoApplyTheme && _gui->theme != NULL)
        //widget->applyTheme(_gui->theme, true);

    grid.add(widget, newRow);

    updatePositions();
    //if (autoFitContents)
        //fitContents();
            
    //if(_gui != NULL)
        //_gui->registerWidget(widget);
}

// pin to current x,y
void Group::pin(Widget* widget, int x, int y)
{
    if (widget != NULL)
    {
        widget->pos.x = pos.x + x;
        widget->pos.y = pos.y + y;
        
        widget->setGui(_gui);
        widget->setPanel(_panel);
        widget->setGroup(this);
        setChild(widget);
        //widget->pinned = true;

        /*if (_gui != NULL && _gui->autoApplyTheme && _gui->theme != NULL)
            widget->applyTheme(_gui->theme, true);*/

        pins.push_back(widget);
        //align(widget);
        //if (autoFitContents)
        //    fitContents();
    }

}

inline std::list<Widget*>::iterator FindValue(std::list<Widget*>* ls, Widget* widget)
{
    if (ls == NULL)
        return std::list<Widget*>::iterator();
    for (std::list<Widget*>::iterator e = ls->begin(); e != ls->end(); ++e)
    {
        if (*e == widget)
            return e;
    }
    return ls->end();
}

// FindValue needs testing...  The &pins == NULL return value is weird.
void Group::unpin(Widget* widget)
{
    if (widget == NULL)
        return;
    std::list<Widget*>::iterator e = FindValue(&pins, widget);
    if (e != std::list<Widget*>::iterator() && e != pins.end())
    {
        //(*e)->pinned = false;
        pins.erase(e);
        return;
    }
    //if (autoFitContents)
        //fitContents();
}

void Group::resize(Uint16 w, Uint16 h, bool parentResize)
{
    //Uint16 oldW = area.w;
    //Uint16 oldH = area.h;
    dims.w = w;
    dims.h = h;
    if (dims.w < 10)
        dims.w = 10;
    if (dims.h < 10)
        dims.h = 10;

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        //if ((*e)->relPinCoords != NULL)
            //(*e)->updateRelCoords();
    }
}

void Group::update()
{
    /*int xScroll = (scrollX == NULL? 0 : scrollX->value*area.w);
    int yScroll = (scrollY == NULL? 0 : scrollY->value*area.h);
    int dx2 = xScroll - oldXScroll;
    int dy2 = yScroll - oldYScroll;
    oldXScroll = xScroll;
    oldYScroll = yScroll;*/
    Widget* w;
    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = (*e);
        if (w != NULL)
        {
            /*if (w->scrollable)
            {
                w->move(-dx2, -dy2);
            }*/

            w->update();
            //align(w);
        }
    }

    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL)
            {
                //w->move(-dx2, -dy2);
                w->update();
            }
        }
    }
}

// change dimensions of the group to fit the widgets
/*void Group::fitContents(bool usePinned)
{
    // Get extents according to widget positions
    //updatePositions(usePinned);  // This is done often enough...  Do I need it here?
    resize(extentX, extentY);

    // Reset the scrollbars so that the widget fit right into the group
    if (scrollX != NULL)
        scrollX->setValue(0);
    if (scrollY != NULL)
        scrollY->setValue(0);
}*/

void Group::updatePositions(bool usePinnedExtents)
{
    //extentX = 0;
    //extentY = 0;
    int cOffset = 0;
    int rOffset = 0;

    unsigned int max = 0;

    Widget* w = NULL;
    bool gotOne = 0;

    //int xScroll = oldXScroll = (scrollX == NULL? 0 : scrollX->value*area.w);
    //int yScroll = oldYScroll = (scrollY == NULL? 0 : scrollY->value*area.h);
    int xScroll = 0;
    int yScroll = 0;

    // figure out the positions of all grid widgets
    switch (alignment)
    {
    case ALIGN_UP_LEFT:
        for (Uint16 j = 0; j < grid.columns; j++)
        {
            for (Uint16 i = 0; i < grid.rows; i++)
            {
                w = grid.get(i, j);
                if (w != NULL)
                {
                    w->pos.x = pos.x + displacement.left + xPadding + cOffset - xScroll;
                    w->pos.y = pos.y + displacement.up + yPadding + rOffset - yScroll;
                    rOffset += w->dims.h + yPadding;
                    if (max < w->dims.w)
                        max = w->dims.w;
                    gotOne = 1;
                }
            }
            extentY = rOffset > extentY? rOffset : extentY;
            rOffset = 0;
            if (gotOne)
                cOffset += max + xPadding;
            max = 0;
            gotOne = 0;
        }

        extentX = cOffset + displacement.left + xPadding;
        extentY += displacement.up + yPadding;
        break;
    case ALIGN_LEFT_UP:
    default:
        for (Uint16 i = 0; i < grid.contents.size(); i++)
        {
            for (Uint16 j = 0; j < grid.contents[i].size(); j++)
            {
                w = grid.get(i, j);
                if (w != NULL)
                {
                    w->pos.x = pos.x + displacement.left + xPadding + cOffset - xScroll;
                    w->pos.y = pos.y + displacement.up + yPadding + rOffset - yScroll;
                    cOffset += w->dims.w + xPadding;
                    if (max < w->dims.h)
                        max = w->dims.h;
                    gotOne = 1;
                }
            }
            extentX = cOffset > extentX? cOffset : extentX;
            cOffset = 0;
            if (gotOne)
                rOffset += max + yPadding;
            max = 0;
            gotOne = 0;
        }

        extentY = rOffset + displacement.up + yPadding;
        extentX += displacement.left + xPadding;
        break;
    }

    // Modify extents according to pinned widgets
    if (usePinnedExtents)
    {
        // Loop over pins...  This could be bad if you keep fitting the contents, but the pins are docked to the edge!
        // It would keep expanding!  Maybe I need to exempt the docked ones?
    }
}


/*void Group::setScroll(ScrollBar* scrollbar, DirectionEnum direction)
{
    if (direction == UP || direction == DOWN)
        scrollY = scrollbar;
    else
        scrollX = scrollbar;
    updatePositions();
    if (scrollX != NULL || scrollY != NULL)
        grabScrollFocus = true;
    else
        grabScrollFocus = false;
}*/

void Group::move(int x, int y, bool relative)
{
    int dx = x, dy = y;
    if (!relative)
    {
        dx -= pos.x;
        dy -= pos.y;
    }
    pos.x += dx;
    pos.y += dy;
    Widget* w;
    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL)
            {
                w->move(dx, dy);
            }
        }
    }

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL)
        {
            w->move(dx, dy);
        }
    }

}


/*void Group::align(Widget* widget)
{
    if (widget != NULL)
    {
        switch (widget->getDock())
        {
        case DOCK_NONE:
            break;
        case DOCK_UP:
            widget->move(widget->area.x, area.y + widget->padding.up, false);
            break;
        case DOCK_UP_LEFT:
            widget->move(area.x + widget->padding.left, area.y + widget->padding.up, false);
            break;
        case DOCK_LEFT:
            widget->move(area.x + widget->padding.left, widget->area.y, false);
            break;
        case DOCK_DOWN_LEFT:
            widget->move(area.x + widget->padding.left, area.y + area.h - widget->area.h - 1 - widget->padding.down, false);
            break;
        case DOCK_DOWN:
            widget->move(widget->area.x, area.y + area.h - widget->area.h - 1 - widget->padding.down, false);
            break;
        case DOCK_DOWN_RIGHT:
            widget->move(area.x + area.w - widget->area.w - 1 - widget->padding.right, area.y + area.h - widget->area.h - 1 - widget->padding.down, false);
            break;
        case DOCK_RIGHT:
            widget->move(area.x + area.w - widget->area.w - 1 - widget->padding.right, widget->area.y, false);
            break;
        case DOCK_UP_RIGHT:
            widget->move(area.x + area.w - widget->area.w - 1 - widget->padding.right, area.y + widget->padding.up, false);
            break;
        case DOCK_CENTER:
            widget->move(area.x + (area.w - widget->area.w)/2, area.y + (area.h - widget->area.h)/2, false);
            break;
        default:
            break;
        }
    }
}*/

/*void Group::applyTheme(Theme* theme, bool recursive)
{
    if (theme == NULL)
        return;

    for (list<ThemeItem>::iterator e = theme->items.begin(); e != theme->items.end(); ++e)
    {
        bool first = e->level & THEMEITEM_FIRST, second = e->level & THEMEITEM_SECOND
                     , third = e->level & THEMEITEM_THIRD, fourth = e->level & THEMEITEM_FOURTH
                               , sub1 = e->level & THEMEITEM_SUB1, sub2 = e->level & THEMEITEM_SUB2
                                        , sub3 = e->level & THEMEITEM_SUB3, sub4 = e->level & THEMEITEM_SUB4;
        if (e->widgetType == _type && first && !(second || third || fourth) && !(sub1 || sub2 || sub3 || sub4))
        {
            if (e->box != NULL)
                setBox(e->box);
            if (e->frame != NULL)
                setFrame(e->frame);
            if (e->design != NULL)
                setDesign(e->design);
        }
    }

    if (recursive)
    {
        Widget* w;
        for (Uint16 i = 0; i < grid.contents.size(); i++)
        {
            for (Uint16 j = 0; j < grid.contents[i].size(); j++)
            {
                w = grid.get(i, j);
                if (w != NULL)
                {
                    w->applyTheme(theme, recursive);
                }
            }
        }

        for (widgetList::iterator e = pins.begin(); e != pins.end(); ++e)
        {
            w = *e;
            if (w != NULL)
            {
                w->applyTheme(theme, recursive);
            }
        }
    }
}*/

void Group::setGui(Gui* Gui)
{
    if(Gui != NULL)
        Gui->registerWidget(this);
    
    _gui = Gui;

    Widget* w;
    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL)
            {
                w->setGui(Gui);
            }
        }
    }

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL)
        {
            w->setGui(Gui);
        }
    }
}

void Group::setPanel(Panel* Panel)
{
    _panel = Panel;

    Widget* w;
    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL)
            {
                w->setPanel(Panel);
            }
        }
    }

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL)
        {
            w->setPanel(Panel);
        }
    }
}

void Group::setGroup(Group* Group)
{
    _group = Group;

    Widget* w;
    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL)
            {
                w->setGroup(this);
            }
        }
    }

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL)
        {
            w->setGroup(this);
        }
    }
}

Widget* Group::mouseWheelEvent(Sint16 mx, Sint16 my)
{
    Widget* w;

    // First, look for groups.  Then look for grabby widgets.
    // Here, we'll ask any group under the mouse to return the widget that
    // it finds with this same function.  If it's not a group that we're over,
    // make sure that it isn't pretending to be a group (like ListBox).
    // If it's a fake group, then it should receive the event.
    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL && InRect(mx, my, w->pos, w->dims))
        {
            if (w->getType() == GROUP)
            {
                w = static_cast<Group*>(w)->mouseWheelEvent(mx, my);
                if (w != NULL)
                    return w;  // Return the widget that was passed through
            }
            //else if(w->isFakeGroup && w->grabMouseWheelFocus)
            //    return w;
        }
    }

    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL && InRect(mx, my, w->pos, w->dims))
            {
                if (w->getType() == GROUP)
                {
                    w = static_cast<Group*>(w)->mouseWheelEvent(mx, my);
                    if (w != NULL)
                        return w;  // Return the widget that was passed through
                }
                //else if(w->isFakeGroup && w->grabMouseWheelFocus)
                //    return w;
            }
        }
    }

    // Now check for widgets.

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        //if (w != NULL && w->grabMouseWheelFocus)
        //    return w;
    }

    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            //if (w != NULL && w->grabMouseWheelFocus)
            //    return w;
        }
    }
    return NULL;
}

void Group::draw(SDL_Rect* clipRect)
{
    if (_folded || _hidden || _gui == NULL || _gui->getRenderer() == NULL)
        return;


    SDL_Rect area = MakeRect(pos.x, pos.y, dims.w, dims.h);
    DRAW_BOX;

    SDL_Rect clip;
    _gui->getRenderer()->RectIntersect(*clipRect, area, clip);
    _gui->getRenderer()->SetClip(clip);

    Widget* w;
    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL)
            {
                _gui->getRenderer()->SetClip(clip);
                w->draw(&clip);
            }
        }
    }

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL)
        {
            _gui->getRenderer()->SetClip(clip);
            w->draw(&clip);
        }
    }

    if (clipRect != NULL)
        _gui->getRenderer()->SetClip(*clipRect);
    DRAW_FRAME;
}

Widget* Group::findWidget(int mx, int my)
{
    if (_folded || _hidden || !InRect(mx, my, pos, dims))
        return NULL;
    Widget* w = NULL;

    for (std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); ++e)
    {
        w = *e;
        if (w != NULL)
        {
            w = w->findWidget(mx, my);
            if (w != NULL)
                return w;
        }
    }

    for (Uint16 i = 0; i < grid.contents.size(); i++)
    {
        for (Uint16 j = 0; j < grid.contents[i].size(); j++)
        {
            w = grid.get(i, j);
            if (w != NULL)
            {
                w = w->findWidget(mx, my);
                if (w != NULL)
                    return w;
            }
        }
    }

    return this;
}

/*Widget* Group::scroll(DirectionEnum direction, float numIncrements)
{
    if (_folded || _hidden) // Should I really ignore these events?
        return NULL;
    if (direction == UP || direction == DOWN)
    {
        if (scrollY != NULL)
            return scrollY->scroll(direction == UP? -numIncrements : numIncrements);
        return scrollY;
    }
    else
    {
        if (scrollX != NULL)
            return scrollX->scroll(direction == LEFT? -numIncrements : numIncrements);
        return scrollX;
    }
}*/



TiXmlElement* Group::save(TiXmlElement* parent)
{
    TiXmlElement* w = new TiXmlElement("Group");
    parent->LinkEndChild(w);
    
    saveWidgetAttributes(w);
    
    w->SetAttribute("gridRows", grid.rows);
    w->SetAttribute("gridColumns", grid.columns);
    
    w->SetAttribute("alignment", alignment);
    w->SetAttribute("xPadding", xPadding);
    w->SetAttribute("yPadding", yPadding);
    w->SetAttribute("autoFitContents", autoFitContents);
    
    w->SetAttribute("displacement", displacement.toString().c_str());
    
    TiXmlElement* g = new TiXmlElement("Grid");
    w->LinkEndChild(g);
    // FIXME: Save IDs from grid widgets instead of dumping them all here
    for(std::vector< std::vector<Widget*> >::iterator e = grid.contents.begin(); e != grid.contents.end(); e++)
    {
        for(std::vector<Widget*>::iterator f = e->begin(); f != e->end(); f++)
        {
            if(*f != NULL)
                (*f)->save(g);
        }
    }
    
    g = new TiXmlElement("Pins");
    w->LinkEndChild(g);
    
    for(std::list<Widget*>::iterator e = pins.begin(); e != pins.end(); e++)
    {
        (*e)->save(g);
    }
    
    /*
    Grid grid;
    //NavGraph* graph;
    std::list<Widget*> pins;

    //ScrollBar* scrollX;
    //ScrollBar* scrollY;

    enum AlignEnum
    {
        //ALIGN_NONE,
        ALIGN_LEFT_UP,
        //ALIGN_LEFT_DOWN,
        //ALIGN_RIGHT_UP,
        //ALIGN_RIGHT_DOWN,
        ALIGN_UP_LEFT
        //ALIGN_UP_RIGHT,
        //ALIGN_DOWN_LEFT,
        //ALIGN_DOWN_RIGHT,
        //ALIGN_CENTER
    };

    AlignEnum alignment;
    int xPadding, yPadding;
    bool autoFitContents;
    Uint16 extentX;  // How much area the widgets take up
    Uint16 extentY;

    //int oldXScroll, oldYScroll;

    Rect displacement;  // Group side padding
    */
    
    return w;
}



    
}
